import { Api_key, BaseUrl } from '@/utils/RobApi'
import { useTalkHis } from '@/stores/talkHis'

// 定义请求任务类型
interface RequestTask {
  onChunkReceived: (callback: (res: { data: string | ArrayBuffer }) => void) => void
}
export interface Message {
    type: 'user' | 'ai'
    content: string
    time: string
    isStreaming?: boolean
  }
  

// 定义 talkHis 类型
interface TalkHisData {
  event: string
  mode: string
  metadata: {
    usage: {
      prompt_tokens: number
      prompt_unit_price: string
      prompt_price_unit: string
      prompt_price: string
      completion_tokens: number
      completion_unit_price: string
      completion_price_unit: string
      completion_price: string
      total_tokens: number
      total_price: string
      latency: number
      currency: string
    }
    retriever_resources: Array<{
      position: number
      dataset_id: string
      dataset_name: string
      document_id: string
      document_name: string
      segment_id: string
      score: number
      content: string
    }>
  }
  conversation_id: string
  message_id: string
  answer: string
  created_at: number
}

export class ChatService {
  private apiKey: string
  private baseUrl: string
  private talkHisStore: ReturnType<typeof useTalkHis>

  constructor(apiKey: string = Api_key, baseUrl: string = BaseUrl) {
    this.apiKey = apiKey
    this.baseUrl = baseUrl
    this.talkHisStore = useTalkHis()
  }

  // 解码响应数据
  private decodeResponseData(data: string | ArrayBuffer): string {
    // #ifdef H5
    if (typeof TextDecoder !== 'undefined') {
      return new TextDecoder('utf-8').decode(data as ArrayBuffer)
    }
    // #endif

    // #ifdef MP-WEIXIN
    if (typeof data === 'string') {
      return data
    } else if (data instanceof ArrayBuffer) {
      let result = ''
      const uint8Array = new Uint8Array(data)
      for (let i = 0; i < uint8Array.length; i++) {
        result += String.fromCharCode(uint8Array[i])
      }
      return result
    }
    return ''
    // #endif
  }

  // 处理流式响应的通用函数
  private handleStreamResponse(
    data: string | ArrayBuffer | Uint8Array,
    options: {
      fullResponse: string,
      buffer: string,
      conversationId: string,
      messageId: string,
      taskId: string,
      workflowRunId: string,
      createdAt: number,
      isStreamEnded: boolean,
      lastUpdateTime: number,
      updateInterval: number,
      minBufferLen: number,
      onMessageUpdate: (message: Message) => void,
      onStreamEnd: () => void
    }
  ): {
    fullResponse: string,
    buffer: string,
    conversationId: string,
    messageId: string,
    taskId: string,
    workflowRunId: string,
    createdAt: number,
    isStreamEnded: boolean,
    lastUpdateTime: number
  } {
    try {
      let decodedData = ''

      // #ifdef MP-WEIXIN
      if (typeof data === 'string') {
        decodedData = data
      } else if (data instanceof ArrayBuffer) {
        const uint8Array = new Uint8Array(data)
        for (let i = 0; i < uint8Array.length; i++) {
          decodedData += String.fromCharCode(uint8Array[i])
        }
      }
      // #endif

      // #ifdef H5
      if (data instanceof Uint8Array) {
        decodedData = new TextDecoder().decode(data)
      } else {
        decodedData = this.decodeResponseData(data)
      }
      // #endif

      if (!decodedData.trim()) {
        return options
      }

      const lines = decodedData.split('\n\n')

      for (const line of lines) {
        if (!line.trim()) continue

        if (line.startsWith('data:')) {
          const jsonStr = line.slice(5).trim()
          if (!jsonStr) continue

          try {
            if (!jsonStr.startsWith('{') || !jsonStr.endsWith('}')) {
              continue
            }

            const data = JSON.parse(jsonStr)

            if (data.event === 'message') {
              const newContent = data.answer || ''
              options.buffer += newContent
              const now = Date.now()
              if (now - options.lastUpdateTime >= options.updateInterval || options.buffer.length >= options.minBufferLen) {
                options.fullResponse += options.buffer
                options.onMessageUpdate({
                  type: 'ai',
                  content: options.fullResponse,
                  time: new Date().toLocaleTimeString(),
                  isStreaming: true
                })
                options.buffer = ''
                options.lastUpdateTime = now
              }
              options.conversationId = data.conversation_id || options.conversationId
              options.messageId = data.message_id || options.messageId
              options.taskId = data.task_id || options.taskId
              options.workflowRunId = data.workflow_run_id || options.workflowRunId
              options.createdAt = data.created_at || options.createdAt
            } else if (data.event === 'message_end') {
              options.isStreamEnded = true
              options.fullResponse += options.buffer
              options.onMessageUpdate({
                type: 'ai',
                content: options.fullResponse,
                time: new Date().toLocaleTimeString(),
                isStreaming: false
              })
              options.buffer = ''

              // 保存对话历史
              if (options.conversationId && options.messageId) {
                const talkHisData: TalkHisData = {
                  event: 'message_end',
                  mode: 'streaming',
                  metadata: {
                    usage: {
                      prompt_tokens: 0,
                      prompt_unit_price: '0',
                      prompt_price_unit: 'token',
                      prompt_price: '0',
                      completion_tokens: 0,
                      completion_unit_price: '0',
                      completion_price_unit: 'token',
                      completion_price: '0',
                      total_tokens: 0,
                      total_price: '0',
                      latency: 0,
                      currency: 'CNY'
                    },
                    retriever_resources: [{
                      position: 0,
                      dataset_id: '',
                      dataset_name: '',
                      document_id: '',
                      document_name: '',
                      segment_id: '',
                      score: 0,
                      content: ''
                    }]
                  },
                  conversation_id: options.conversationId,
                  message_id: options.messageId,
                  answer: options.fullResponse,
                  created_at: options.createdAt
                }
                this.talkHisStore.setTalkHis(talkHisData)
              }
              options.onStreamEnd()
            }
          } catch (parseError) {
            console.warn('JSON parse error:', {
              error: parseError,
              rawData: jsonStr,
              dataLength: jsonStr.length,
              isComplete: jsonStr.startsWith('{') && jsonStr.endsWith('}')
            })
            continue
          }
        }
      }
    } catch (e) {
      console.error('Stream processing error:', e)
    }
    return options
  }

  // 发送消息
  async sendMessage(
    userMessage: string,
    onMessageUpdate: (message: Message) => void,
    onStreamEnd: () => void
  ): Promise<void> {
    const params = {
      inputs: {},
      query: userMessage,
      response_mode: 'streaming',
      conversation_id: '',
      user: 'abc-123',
      auto_generate_name: true
    }

    let state = {
      fullResponse: '',
      buffer: '',
      conversationId: '',
      messageId: '',
      taskId: '',
      workflowRunId: '',
      createdAt: 0,
      isStreamEnded: false,
      lastUpdateTime: Date.now()
    }

    const updateInterval = 1000 // 最小更新间隔（毫秒）
    const minBufferLen = 8 // 累计到8字符也强制刷新

    try {
      // #ifdef MP-WEIXIN
      const requestTask = uni.request({
        url: this.baseUrl + '/chat-messages',
        method: 'POST',
        data: params,
        enableChunked: true,
        responseType: 'text',
        header: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json'
        },
        success: (res) => {
          if (!state.isStreamEnded) {
            onStreamEnd()
          }
        },
        fail: (error) => {
          onMessageUpdate({
            type: 'ai',
            content: '抱歉，请求失败，请重试',
            time: new Date().toLocaleTimeString(),
            isStreaming: false
          })
        }
      }) as unknown as RequestTask

      requestTask.onChunkReceived(res => {
        state = this.handleStreamResponse(res.data, {
          ...state,
          updateInterval,
          minBufferLen,
          onMessageUpdate,
          onStreamEnd
        })
      })
      // #endif

      // #ifdef H5
      const response = await fetch(this.baseUrl + '/chat-messages', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(params)
      })

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }

      const reader = response.body?.getReader()
      if (!reader) {
        throw new Error('No reader available')
      }

      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        state = this.handleStreamResponse(value, {
          ...state,
          updateInterval,
          minBufferLen,
          onMessageUpdate,
          onStreamEnd
        })
      }
      // #endif

    } catch (error) {
      console.error('发送消息失败:', error)
      onMessageUpdate({
        type: 'ai',
        content: '抱歉，发送消息失败，请重试',
        time: new Date().toLocaleTimeString(),
        isStreaming: false
      })
    }
  }
} 